Dogs vs. Cats - CNN using MobileNetV2

Name: Burhan Hadi Butt

Enrollment: 03-134211-008

Class: BSCS - 7A

Import Necessary Libraries¶

In [1]:
import os
import random
import numpy as np
import pandas as pd
import cv2
from tqdm import tqdm
import matplotlib.pyplot as plt
import seaborn as sns
import itertools
import zipfile
import splitfolders
import shutil

import tensorflow as tf

from keras.applications import MobileNetV2
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, EarlyStopping, LearningRateScheduler
from tensorflow.keras import layers, models, Sequential
from tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten
from tensorflow.keras.optimizers import Adam, RMSprop, SGD
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.preprocessing import image, image_dataset_from_directory
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.models import load_model

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

from matplotlib.ticker import (MultipleLocator, FormatStrFormatter)
from dataclasses import dataclass

import warnings
warnings.simplefilter(action='ignore', category=UserWarning)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
tf.get_logger().setLevel('ERROR')
In [2]:
# Set prerequisites

# Set random seeds for reproducibility
random.seed(42)
np.random.seed(42)
tf.random.set_seed(42)

Load Dataset¶

In [3]:
# Define the directories for dataset

input_data_dir = "dataset/dogs-vs-cats.zip"
extracted_input_data_dir = "dataset/dogs-vs-cats"
In [4]:
# Unzip the dataset

# Create the directory if it doesn't exist
os.makedirs(extracted_input_data_dir, exist_ok=True)

# Extract the contents of the zip file
with zipfile.ZipFile(input_data_dir, 'r') as zip_ref:
    zip_ref.extractall(extracted_input_data_dir)
In [5]:
# Define the directories for train and test folders

train_data_dir = "dataset/dogs-vs-cats/train.zip"
test_data_dir = "dataset/dogs-vs-cats/test1.zip"
extracted_train_test_data_dir = "dataset/dogs-vs-cats"
In [6]:
# Uzip the train and test folders

# Create the directory if they doesn't exist
os.makedirs(extracted_train_test_data_dir, exist_ok=True)
os.makedirs(extracted_train_test_data_dir, exist_ok=True)

# Extract the contents of the zip files
with zipfile.ZipFile(train_data_dir, 'r') as zip_ref:
    zip_ref.extractall(extracted_train_test_data_dir)
with zipfile.ZipFile(test_data_dir, 'r') as zip_ref:
    zip_ref.extractall(extracted_train_test_data_dir)
In [7]:
# Load the test data

test_data = pd.read_csv('dataset/dogs-vs-cats/sampleSubmission.csv')

# Convert the columns values to strings
test_data['id'] = test_data['id'].astype(str)
test_data['label'] = test_data['label'].astype(str)

Dataset Preprocessing¶

In [8]:
# Dataset defination

# Training and testing path
train_data_dir = "dataset/dogs-vs-cats/train"
test_data_dir = "dataset/dogs-vs-cats/test1"

# Create the train dataframe
filenames = os.listdir(train_data_dir)
class_names = [x.split(".")[0] for x in filenames]

data = pd.DataFrame({"filename": filenames, "labels": class_names})

nb_classes = len(class_names)

# Define image dimensions
img_height = 224
img_width = 224

# Define batch size
batch_size = 32

# Define dataset shape
input_shape = (img_height, img_width, 3)
In [9]:
# Number of samples in train and test set

# Get the number of samples in the train set
n_train = len(os.listdir(train_data_dir))

# Get the number of samples in the test set
n_test = len(os.listdir(test_data_dir))

# Print the number of samples in the train and test sets
print("Number of training examples: {}".format(n_train))
print("Number of testing examples: {}".format(n_test))
Number of training examples: 25000
Number of testing examples: 12500
In [10]:
# Display sample images

# Get a list of filenames in the train directory
filenames = os.listdir(train_data_dir)

# Define the number of samples to display
num_samples = 8

# Define a counter for the number of displayed images
displayed_images = 0

# Plot the sample images for cats and dogs
plt.figure(figsize=(15, 15))
plt.suptitle("Sample Images for Cats", fontsize=20)
plt.subplots_adjust(top=0.93)

for filename in filenames:
    if "cat" in filename and displayed_images < num_samples:
        img_path = os.path.join(train_data_dir, filename)
        img = cv2.imread(img_path)
        if img is not None:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            
            # Plot the image
            ax = plt.subplot(4, 4, displayed_images + 1)
            plt.imshow(img)
            plt.title(filename)
            plt.axis("off")
            
            displayed_images += 1

plt.show()

# Reset the counter
displayed_images = 0

# Reset the counter
displayed_images = 0

# Plot the sample images for dogs
plt.figure(figsize=(15, 15))
plt.suptitle("Sample Images for Dogs", fontsize=20)
plt.subplots_adjust(top=0.93)

for filename in filenames:
    if "dog" in filename and displayed_images < num_samples:
        img_path = os.path.join(train_data_dir, filename)
        img = cv2.imread(img_path)
        if img is not None:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            
            # Plot the image
            ax = plt.subplot(4, 4, displayed_images + 1)
            plt.imshow(img)
            plt.title(filename)
            plt.axis("off")
            
            displayed_images += 1

plt.show()
No description has been provided for this image
No description has been provided for this image
In [11]:
# Apply Data Augmentation

# Split the data into training and testing sets with a ratio of 80% training and 20% testing
train_data, test_data = train_test_split(data, test_size=0.2, random_state=42)

# Define data generators for training and testing data
train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    validation_split=0.1
)

test_datagen = ImageDataGenerator(rescale=1./255)

# Define data generators for training and testing data
train_generator = train_datagen.flow_from_dataframe(
    dataframe=train_data,
    directory=train_data_dir,
    x_col="filename",
    y_col="labels",
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode="binary",
    subset="training"
)

validation_generator = train_datagen.flow_from_dataframe(
    dataframe=train_data,
    directory=train_data_dir,
    x_col="filename",
    y_col="labels",
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode="binary",
    subset="validation"
)

# Create a test generator for testing data
test_generator = test_datagen.flow_from_dataframe(
    dataframe=test_data,
    directory=train_data_dir,
    x_col="filename",
    y_col="labels",
    target_size=(img_height, img_width),
    batch_size=batch_size,
    class_mode="binary",
    shuffle=False
)

# Get the number of training and testing examples
n_train = len(train_generator.labels)
n_validation = len(validation_generator.labels)
n_test = len(test_generator.labels)

print("\nNumber of training examples:", n_train)
print("Number of validation examples:", n_validation)
print("Number of testing examples:", n_test)
print("\nEach image is of size: {}x{}x{}".format(img_height, img_width, 3))
Found 18000 validated image filenames belonging to 2 classes.
Found 2000 validated image filenames belonging to 2 classes.
Found 5000 validated image filenames belonging to 2 classes.

Number of training examples: 18000
Number of validation examples: 2000
Number of testing examples: 5000

Each image is of size: 224x224x3
In [12]:
# Display augmented images

plt.figure(figsize=(15, 15))
plt.suptitle('Augmented Images', fontsize=20)
plt.subplots_adjust(top=0.93)
for i in range(12):
    ax = plt.subplot(4, 4, i + 1)
    batch = next(train_generator)
    plt.imshow(batch[0][0])
    plt.axis("off")
plt.show()
No description has been provided for this image
In [13]:
# Display the number of samples in each set

labels = ['Cat', 'Dog']

# Get the count of each label in the training, validation, and testing sets
label1, count1 = np.unique(train_generator.labels, return_counts=True)
label2, count2 = np.unique(validation_generator.labels, return_counts=True)
label3, count3 = np.unique(test_generator.labels, return_counts=True)

# Create dataframes for each set
uni1 = pd.DataFrame(data=count1, index=labels, columns=['Count1'])
uni2 = pd.DataFrame(data=count2, index=labels, columns=['Count2'])
uni3 = pd.DataFrame(data=count3, index=labels, columns=['Count3'])

# Plot the bar charts
plt.figure(figsize=(20, 6), dpi=200)

plt.subplot(131)
sns.barplot(data=uni1, x=uni1.index, y='Count1', hue=uni1.index, palette=['royalblue', 'firebrick'], width=0.2, legend=False).set_title('Class distribution in Training set', fontsize=15)
plt.xlabel('Labels', fontsize=12)
plt.ylabel('Count', fontsize=12)

plt.subplot(132)
sns.barplot(data=uni2, x=uni2.index, y='Count2', hue=uni2.index, palette=['royalblue', 'firebrick'], width=0.2, legend=False).set_title('Class distribution in Validation set', fontsize=15)
plt.xlabel('Labels', fontsize=12)
plt.ylabel('Count', fontsize=12)

plt.subplot(133)
sns.barplot(data=uni3, x=uni3.index, y='Count3', hue=uni3.index, palette=['royalblue', 'firebrick'], width=0.2, legend=False).set_title('Class distribution in Testing set', fontsize=15)
plt.xlabel('Labels', fontsize=12)
plt.ylabel('Count', fontsize=12)

plt.show()
No description has been provided for this image

MobileNetV2 Trained Model¶

In [14]:
# Load pre-trained MobileNetV2 model

base_model = MobileNetV2(include_top=False, weights='imagenet', input_shape=input_shape)

# Print base model summary
base_model.summary()
Model: "mobilenetv2_1.00_224"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 input_1 (InputLayer)           [(None, 224, 224, 3  0           []                               
                                )]                                                                
                                                                                                  
 Conv1 (Conv2D)                 (None, 112, 112, 32  864         ['input_1[0][0]']                
                                )                                                                 
                                                                                                  
 bn_Conv1 (BatchNormalization)  (None, 112, 112, 32  128         ['Conv1[0][0]']                  
                                )                                                                 
                                                                                                  
 Conv1_relu (ReLU)              (None, 112, 112, 32  0           ['bn_Conv1[0][0]']               
                                )                                                                 
                                                                                                  
 expanded_conv_depthwise (Depth  (None, 112, 112, 32  288        ['Conv1_relu[0][0]']             
 wiseConv2D)                    )                                                                 
                                                                                                  
 expanded_conv_depthwise_BN (Ba  (None, 112, 112, 32  128        ['expanded_conv_depthwise[0][0]']
 tchNormalization)              )                                                                 
                                                                                                  
 expanded_conv_depthwise_relu (  (None, 112, 112, 32  0          ['expanded_conv_depthwise_BN[0][0
 ReLU)                          )                                ]']                              
                                                                                                  
 expanded_conv_project (Conv2D)  (None, 112, 112, 16  512        ['expanded_conv_depthwise_relu[0]
                                )                                [0]']                            
                                                                                                  
 expanded_conv_project_BN (Batc  (None, 112, 112, 16  64         ['expanded_conv_project[0][0]']  
 hNormalization)                )                                                                 
                                                                                                  
 block_1_expand (Conv2D)        (None, 112, 112, 96  1536        ['expanded_conv_project_BN[0][0]'
                                )                                ]                                
                                                                                                  
 block_1_expand_BN (BatchNormal  (None, 112, 112, 96  384        ['block_1_expand[0][0]']         
 ization)                       )                                                                 
                                                                                                  
 block_1_expand_relu (ReLU)     (None, 112, 112, 96  0           ['block_1_expand_BN[0][0]']      
                                )                                                                 
                                                                                                  
 block_1_pad (ZeroPadding2D)    (None, 113, 113, 96  0           ['block_1_expand_relu[0][0]']    
                                )                                                                 
                                                                                                  
 block_1_depthwise (DepthwiseCo  (None, 56, 56, 96)  864         ['block_1_pad[0][0]']            
 nv2D)                                                                                            
                                                                                                  
 block_1_depthwise_BN (BatchNor  (None, 56, 56, 96)  384         ['block_1_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_1_depthwise_relu (ReLU)  (None, 56, 56, 96)   0           ['block_1_depthwise_BN[0][0]']   
                                                                                                  
 block_1_project (Conv2D)       (None, 56, 56, 24)   2304        ['block_1_depthwise_relu[0][0]'] 
                                                                                                  
 block_1_project_BN (BatchNorma  (None, 56, 56, 24)  96          ['block_1_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_2_expand (Conv2D)        (None, 56, 56, 144)  3456        ['block_1_project_BN[0][0]']     
                                                                                                  
 block_2_expand_BN (BatchNormal  (None, 56, 56, 144)  576        ['block_2_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_2_expand_relu (ReLU)     (None, 56, 56, 144)  0           ['block_2_expand_BN[0][0]']      
                                                                                                  
 block_2_depthwise (DepthwiseCo  (None, 56, 56, 144)  1296       ['block_2_expand_relu[0][0]']    
 nv2D)                                                                                            
                                                                                                  
 block_2_depthwise_BN (BatchNor  (None, 56, 56, 144)  576        ['block_2_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_2_depthwise_relu (ReLU)  (None, 56, 56, 144)  0           ['block_2_depthwise_BN[0][0]']   
                                                                                                  
 block_2_project (Conv2D)       (None, 56, 56, 24)   3456        ['block_2_depthwise_relu[0][0]'] 
                                                                                                  
 block_2_project_BN (BatchNorma  (None, 56, 56, 24)  96          ['block_2_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_2_add (Add)              (None, 56, 56, 24)   0           ['block_1_project_BN[0][0]',     
                                                                  'block_2_project_BN[0][0]']     
                                                                                                  
 block_3_expand (Conv2D)        (None, 56, 56, 144)  3456        ['block_2_add[0][0]']            
                                                                                                  
 block_3_expand_BN (BatchNormal  (None, 56, 56, 144)  576        ['block_3_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_3_expand_relu (ReLU)     (None, 56, 56, 144)  0           ['block_3_expand_BN[0][0]']      
                                                                                                  
 block_3_pad (ZeroPadding2D)    (None, 57, 57, 144)  0           ['block_3_expand_relu[0][0]']    
                                                                                                  
 block_3_depthwise (DepthwiseCo  (None, 28, 28, 144)  1296       ['block_3_pad[0][0]']            
 nv2D)                                                                                            
                                                                                                  
 block_3_depthwise_BN (BatchNor  (None, 28, 28, 144)  576        ['block_3_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_3_depthwise_relu (ReLU)  (None, 28, 28, 144)  0           ['block_3_depthwise_BN[0][0]']   
                                                                                                  
 block_3_project (Conv2D)       (None, 28, 28, 32)   4608        ['block_3_depthwise_relu[0][0]'] 
                                                                                                  
 block_3_project_BN (BatchNorma  (None, 28, 28, 32)  128         ['block_3_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_4_expand (Conv2D)        (None, 28, 28, 192)  6144        ['block_3_project_BN[0][0]']     
                                                                                                  
 block_4_expand_BN (BatchNormal  (None, 28, 28, 192)  768        ['block_4_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_4_expand_relu (ReLU)     (None, 28, 28, 192)  0           ['block_4_expand_BN[0][0]']      
                                                                                                  
 block_4_depthwise (DepthwiseCo  (None, 28, 28, 192)  1728       ['block_4_expand_relu[0][0]']    
 nv2D)                                                                                            
                                                                                                  
 block_4_depthwise_BN (BatchNor  (None, 28, 28, 192)  768        ['block_4_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_4_depthwise_relu (ReLU)  (None, 28, 28, 192)  0           ['block_4_depthwise_BN[0][0]']   
                                                                                                  
 block_4_project (Conv2D)       (None, 28, 28, 32)   6144        ['block_4_depthwise_relu[0][0]'] 
                                                                                                  
 block_4_project_BN (BatchNorma  (None, 28, 28, 32)  128         ['block_4_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_4_add (Add)              (None, 28, 28, 32)   0           ['block_3_project_BN[0][0]',     
                                                                  'block_4_project_BN[0][0]']     
                                                                                                  
 block_5_expand (Conv2D)        (None, 28, 28, 192)  6144        ['block_4_add[0][0]']            
                                                                                                  
 block_5_expand_BN (BatchNormal  (None, 28, 28, 192)  768        ['block_5_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_5_expand_relu (ReLU)     (None, 28, 28, 192)  0           ['block_5_expand_BN[0][0]']      
                                                                                                  
 block_5_depthwise (DepthwiseCo  (None, 28, 28, 192)  1728       ['block_5_expand_relu[0][0]']    
 nv2D)                                                                                            
                                                                                                  
 block_5_depthwise_BN (BatchNor  (None, 28, 28, 192)  768        ['block_5_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_5_depthwise_relu (ReLU)  (None, 28, 28, 192)  0           ['block_5_depthwise_BN[0][0]']   
                                                                                                  
 block_5_project (Conv2D)       (None, 28, 28, 32)   6144        ['block_5_depthwise_relu[0][0]'] 
                                                                                                  
 block_5_project_BN (BatchNorma  (None, 28, 28, 32)  128         ['block_5_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_5_add (Add)              (None, 28, 28, 32)   0           ['block_4_add[0][0]',            
                                                                  'block_5_project_BN[0][0]']     
                                                                                                  
 block_6_expand (Conv2D)        (None, 28, 28, 192)  6144        ['block_5_add[0][0]']            
                                                                                                  
 block_6_expand_BN (BatchNormal  (None, 28, 28, 192)  768        ['block_6_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_6_expand_relu (ReLU)     (None, 28, 28, 192)  0           ['block_6_expand_BN[0][0]']      
                                                                                                  
 block_6_pad (ZeroPadding2D)    (None, 29, 29, 192)  0           ['block_6_expand_relu[0][0]']    
                                                                                                  
 block_6_depthwise (DepthwiseCo  (None, 14, 14, 192)  1728       ['block_6_pad[0][0]']            
 nv2D)                                                                                            
                                                                                                  
 block_6_depthwise_BN (BatchNor  (None, 14, 14, 192)  768        ['block_6_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_6_depthwise_relu (ReLU)  (None, 14, 14, 192)  0           ['block_6_depthwise_BN[0][0]']   
                                                                                                  
 block_6_project (Conv2D)       (None, 14, 14, 64)   12288       ['block_6_depthwise_relu[0][0]'] 
                                                                                                  
 block_6_project_BN (BatchNorma  (None, 14, 14, 64)  256         ['block_6_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_7_expand (Conv2D)        (None, 14, 14, 384)  24576       ['block_6_project_BN[0][0]']     
                                                                                                  
 block_7_expand_BN (BatchNormal  (None, 14, 14, 384)  1536       ['block_7_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_7_expand_relu (ReLU)     (None, 14, 14, 384)  0           ['block_7_expand_BN[0][0]']      
                                                                                                  
 block_7_depthwise (DepthwiseCo  (None, 14, 14, 384)  3456       ['block_7_expand_relu[0][0]']    
 nv2D)                                                                                            
                                                                                                  
 block_7_depthwise_BN (BatchNor  (None, 14, 14, 384)  1536       ['block_7_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_7_depthwise_relu (ReLU)  (None, 14, 14, 384)  0           ['block_7_depthwise_BN[0][0]']   
                                                                                                  
 block_7_project (Conv2D)       (None, 14, 14, 64)   24576       ['block_7_depthwise_relu[0][0]'] 
                                                                                                  
 block_7_project_BN (BatchNorma  (None, 14, 14, 64)  256         ['block_7_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_7_add (Add)              (None, 14, 14, 64)   0           ['block_6_project_BN[0][0]',     
                                                                  'block_7_project_BN[0][0]']     
                                                                                                  
 block_8_expand (Conv2D)        (None, 14, 14, 384)  24576       ['block_7_add[0][0]']            
                                                                                                  
 block_8_expand_BN (BatchNormal  (None, 14, 14, 384)  1536       ['block_8_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_8_expand_relu (ReLU)     (None, 14, 14, 384)  0           ['block_8_expand_BN[0][0]']      
                                                                                                  
 block_8_depthwise (DepthwiseCo  (None, 14, 14, 384)  3456       ['block_8_expand_relu[0][0]']    
 nv2D)                                                                                            
                                                                                                  
 block_8_depthwise_BN (BatchNor  (None, 14, 14, 384)  1536       ['block_8_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_8_depthwise_relu (ReLU)  (None, 14, 14, 384)  0           ['block_8_depthwise_BN[0][0]']   
                                                                                                  
 block_8_project (Conv2D)       (None, 14, 14, 64)   24576       ['block_8_depthwise_relu[0][0]'] 
                                                                                                  
 block_8_project_BN (BatchNorma  (None, 14, 14, 64)  256         ['block_8_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_8_add (Add)              (None, 14, 14, 64)   0           ['block_7_add[0][0]',            
                                                                  'block_8_project_BN[0][0]']     
                                                                                                  
 block_9_expand (Conv2D)        (None, 14, 14, 384)  24576       ['block_8_add[0][0]']            
                                                                                                  
 block_9_expand_BN (BatchNormal  (None, 14, 14, 384)  1536       ['block_9_expand[0][0]']         
 ization)                                                                                         
                                                                                                  
 block_9_expand_relu (ReLU)     (None, 14, 14, 384)  0           ['block_9_expand_BN[0][0]']      
                                                                                                  
 block_9_depthwise (DepthwiseCo  (None, 14, 14, 384)  3456       ['block_9_expand_relu[0][0]']    
 nv2D)                                                                                            
                                                                                                  
 block_9_depthwise_BN (BatchNor  (None, 14, 14, 384)  1536       ['block_9_depthwise[0][0]']      
 malization)                                                                                      
                                                                                                  
 block_9_depthwise_relu (ReLU)  (None, 14, 14, 384)  0           ['block_9_depthwise_BN[0][0]']   
                                                                                                  
 block_9_project (Conv2D)       (None, 14, 14, 64)   24576       ['block_9_depthwise_relu[0][0]'] 
                                                                                                  
 block_9_project_BN (BatchNorma  (None, 14, 14, 64)  256         ['block_9_project[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_9_add (Add)              (None, 14, 14, 64)   0           ['block_8_add[0][0]',            
                                                                  'block_9_project_BN[0][0]']     
                                                                                                  
 block_10_expand (Conv2D)       (None, 14, 14, 384)  24576       ['block_9_add[0][0]']            
                                                                                                  
 block_10_expand_BN (BatchNorma  (None, 14, 14, 384)  1536       ['block_10_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_10_expand_relu (ReLU)    (None, 14, 14, 384)  0           ['block_10_expand_BN[0][0]']     
                                                                                                  
 block_10_depthwise (DepthwiseC  (None, 14, 14, 384)  3456       ['block_10_expand_relu[0][0]']   
 onv2D)                                                                                           
                                                                                                  
 block_10_depthwise_BN (BatchNo  (None, 14, 14, 384)  1536       ['block_10_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_10_depthwise_relu (ReLU)  (None, 14, 14, 384)  0          ['block_10_depthwise_BN[0][0]']  
                                                                                                  
 block_10_project (Conv2D)      (None, 14, 14, 96)   36864       ['block_10_depthwise_relu[0][0]']
                                                                                                  
 block_10_project_BN (BatchNorm  (None, 14, 14, 96)  384         ['block_10_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 block_11_expand (Conv2D)       (None, 14, 14, 576)  55296       ['block_10_project_BN[0][0]']    
                                                                                                  
 block_11_expand_BN (BatchNorma  (None, 14, 14, 576)  2304       ['block_11_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_11_expand_relu (ReLU)    (None, 14, 14, 576)  0           ['block_11_expand_BN[0][0]']     
                                                                                                  
 block_11_depthwise (DepthwiseC  (None, 14, 14, 576)  5184       ['block_11_expand_relu[0][0]']   
 onv2D)                                                                                           
                                                                                                  
 block_11_depthwise_BN (BatchNo  (None, 14, 14, 576)  2304       ['block_11_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_11_depthwise_relu (ReLU)  (None, 14, 14, 576)  0          ['block_11_depthwise_BN[0][0]']  
                                                                                                  
 block_11_project (Conv2D)      (None, 14, 14, 96)   55296       ['block_11_depthwise_relu[0][0]']
                                                                                                  
 block_11_project_BN (BatchNorm  (None, 14, 14, 96)  384         ['block_11_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 block_11_add (Add)             (None, 14, 14, 96)   0           ['block_10_project_BN[0][0]',    
                                                                  'block_11_project_BN[0][0]']    
                                                                                                  
 block_12_expand (Conv2D)       (None, 14, 14, 576)  55296       ['block_11_add[0][0]']           
                                                                                                  
 block_12_expand_BN (BatchNorma  (None, 14, 14, 576)  2304       ['block_12_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_12_expand_relu (ReLU)    (None, 14, 14, 576)  0           ['block_12_expand_BN[0][0]']     
                                                                                                  
 block_12_depthwise (DepthwiseC  (None, 14, 14, 576)  5184       ['block_12_expand_relu[0][0]']   
 onv2D)                                                                                           
                                                                                                  
 block_12_depthwise_BN (BatchNo  (None, 14, 14, 576)  2304       ['block_12_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_12_depthwise_relu (ReLU)  (None, 14, 14, 576)  0          ['block_12_depthwise_BN[0][0]']  
                                                                                                  
 block_12_project (Conv2D)      (None, 14, 14, 96)   55296       ['block_12_depthwise_relu[0][0]']
                                                                                                  
 block_12_project_BN (BatchNorm  (None, 14, 14, 96)  384         ['block_12_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 block_12_add (Add)             (None, 14, 14, 96)   0           ['block_11_add[0][0]',           
                                                                  'block_12_project_BN[0][0]']    
                                                                                                  
 block_13_expand (Conv2D)       (None, 14, 14, 576)  55296       ['block_12_add[0][0]']           
                                                                                                  
 block_13_expand_BN (BatchNorma  (None, 14, 14, 576)  2304       ['block_13_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_13_expand_relu (ReLU)    (None, 14, 14, 576)  0           ['block_13_expand_BN[0][0]']     
                                                                                                  
 block_13_pad (ZeroPadding2D)   (None, 15, 15, 576)  0           ['block_13_expand_relu[0][0]']   
                                                                                                  
 block_13_depthwise (DepthwiseC  (None, 7, 7, 576)   5184        ['block_13_pad[0][0]']           
 onv2D)                                                                                           
                                                                                                  
 block_13_depthwise_BN (BatchNo  (None, 7, 7, 576)   2304        ['block_13_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_13_depthwise_relu (ReLU)  (None, 7, 7, 576)   0           ['block_13_depthwise_BN[0][0]']  
                                                                                                  
 block_13_project (Conv2D)      (None, 7, 7, 160)    92160       ['block_13_depthwise_relu[0][0]']
                                                                                                  
 block_13_project_BN (BatchNorm  (None, 7, 7, 160)   640         ['block_13_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 block_14_expand (Conv2D)       (None, 7, 7, 960)    153600      ['block_13_project_BN[0][0]']    
                                                                                                  
 block_14_expand_BN (BatchNorma  (None, 7, 7, 960)   3840        ['block_14_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_14_expand_relu (ReLU)    (None, 7, 7, 960)    0           ['block_14_expand_BN[0][0]']     
                                                                                                  
 block_14_depthwise (DepthwiseC  (None, 7, 7, 960)   8640        ['block_14_expand_relu[0][0]']   
 onv2D)                                                                                           
                                                                                                  
 block_14_depthwise_BN (BatchNo  (None, 7, 7, 960)   3840        ['block_14_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_14_depthwise_relu (ReLU)  (None, 7, 7, 960)   0           ['block_14_depthwise_BN[0][0]']  
                                                                                                  
 block_14_project (Conv2D)      (None, 7, 7, 160)    153600      ['block_14_depthwise_relu[0][0]']
                                                                                                  
 block_14_project_BN (BatchNorm  (None, 7, 7, 160)   640         ['block_14_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 block_14_add (Add)             (None, 7, 7, 160)    0           ['block_13_project_BN[0][0]',    
                                                                  'block_14_project_BN[0][0]']    
                                                                                                  
 block_15_expand (Conv2D)       (None, 7, 7, 960)    153600      ['block_14_add[0][0]']           
                                                                                                  
 block_15_expand_BN (BatchNorma  (None, 7, 7, 960)   3840        ['block_15_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_15_expand_relu (ReLU)    (None, 7, 7, 960)    0           ['block_15_expand_BN[0][0]']     
                                                                                                  
 block_15_depthwise (DepthwiseC  (None, 7, 7, 960)   8640        ['block_15_expand_relu[0][0]']   
 onv2D)                                                                                           
                                                                                                  
 block_15_depthwise_BN (BatchNo  (None, 7, 7, 960)   3840        ['block_15_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_15_depthwise_relu (ReLU)  (None, 7, 7, 960)   0           ['block_15_depthwise_BN[0][0]']  
                                                                                                  
 block_15_project (Conv2D)      (None, 7, 7, 160)    153600      ['block_15_depthwise_relu[0][0]']
                                                                                                  
 block_15_project_BN (BatchNorm  (None, 7, 7, 160)   640         ['block_15_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 block_15_add (Add)             (None, 7, 7, 160)    0           ['block_14_add[0][0]',           
                                                                  'block_15_project_BN[0][0]']    
                                                                                                  
 block_16_expand (Conv2D)       (None, 7, 7, 960)    153600      ['block_15_add[0][0]']           
                                                                                                  
 block_16_expand_BN (BatchNorma  (None, 7, 7, 960)   3840        ['block_16_expand[0][0]']        
 lization)                                                                                        
                                                                                                  
 block_16_expand_relu (ReLU)    (None, 7, 7, 960)    0           ['block_16_expand_BN[0][0]']     
                                                                                                  
 block_16_depthwise (DepthwiseC  (None, 7, 7, 960)   8640        ['block_16_expand_relu[0][0]']   
 onv2D)                                                                                           
                                                                                                  
 block_16_depthwise_BN (BatchNo  (None, 7, 7, 960)   3840        ['block_16_depthwise[0][0]']     
 rmalization)                                                                                     
                                                                                                  
 block_16_depthwise_relu (ReLU)  (None, 7, 7, 960)   0           ['block_16_depthwise_BN[0][0]']  
                                                                                                  
 block_16_project (Conv2D)      (None, 7, 7, 320)    307200      ['block_16_depthwise_relu[0][0]']
                                                                                                  
 block_16_project_BN (BatchNorm  (None, 7, 7, 320)   1280        ['block_16_project[0][0]']       
 alization)                                                                                       
                                                                                                  
 Conv_1 (Conv2D)                (None, 7, 7, 1280)   409600      ['block_16_project_BN[0][0]']    
                                                                                                  
 Conv_1_bn (BatchNormalization)  (None, 7, 7, 1280)  5120        ['Conv_1[0][0]']                 
                                                                                                  
 out_relu (ReLU)                (None, 7, 7, 1280)   0           ['Conv_1_bn[0][0]']              
                                                                                                  
==================================================================================================
Total params: 2,257,984
Trainable params: 2,223,872
Non-trainable params: 34,112
__________________________________________________________________________________________________
In [15]:
# Freeze the convolutional base of the model

base_model.trainable = False

Version 1: Adam optimizer with Early Stopping¶

In [16]:
# Define hyperparameters

input_shape = (img_height, img_width, 3)
learning_rate = 0.001
loss = 'binary_crossentropy'
metrics=['accuracy']
epochs = 30
In [17]:
# Construct the model

model = Sequential([base_model, Flatten(), Dense(256, activation='relu'), Dense(1, activation='sigmoid')])
In [18]:
# Compile the model

optimizer = Adam(learning_rate=learning_rate)
model.compile(optimizer=optimizer, loss=loss, metrics=metrics)

# Print model summary
model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 mobilenetv2_1.00_224 (Funct  (None, 7, 7, 1280)       2257984   
 ional)                                                          
                                                                 
 flatten (Flatten)           (None, 62720)             0         
                                                                 
 dense (Dense)               (None, 256)               16056576  
                                                                 
 dense_1 (Dense)             (None, 1)                 257       
                                                                 
=================================================================
Total params: 18,314,817
Trainable params: 16,056,833
Non-trainable params: 2,257,984
_________________________________________________________________
In [19]:
# Define early stopping callback

early_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)
In [20]:
# Train the model

model_history_v1 = model.fit(train_generator, epochs=epochs, validation_data=validation_generator, batch_size=batch_size, callbacks=[early_stopping], verbose=1)

# Print the trainging accuracy
training_accuracy = model_history_v1.history['accuracy'][-1]
print("\nTraining Accuracy:", round(training_accuracy, 2))
Epoch 1/30
563/563 [==============================] - 424s 746ms/step - loss: 0.6015 - accuracy: 0.9528 - val_loss: 0.1054 - val_accuracy: 0.9670
Epoch 2/30
563/563 [==============================] - 412s 731ms/step - loss: 0.0861 - accuracy: 0.9661 - val_loss: 0.0872 - val_accuracy: 0.9645
Epoch 3/30
563/563 [==============================] - 405s 720ms/step - loss: 0.0734 - accuracy: 0.9713 - val_loss: 0.0700 - val_accuracy: 0.9695
Epoch 4/30
563/563 [==============================] - 417s 740ms/step - loss: 0.0646 - accuracy: 0.9754 - val_loss: 0.0681 - val_accuracy: 0.9700
Epoch 5/30
563/563 [==============================] - 406s 721ms/step - loss: 0.0663 - accuracy: 0.9740 - val_loss: 0.0595 - val_accuracy: 0.9730
Epoch 6/30
563/563 [==============================] - 409s 727ms/step - loss: 0.0631 - accuracy: 0.9753 - val_loss: 0.0682 - val_accuracy: 0.9715
Epoch 7/30
563/563 [==============================] - 409s 727ms/step - loss: 0.0603 - accuracy: 0.9761 - val_loss: 0.0774 - val_accuracy: 0.9700
Epoch 8/30
563/563 [==============================] - 413s 734ms/step - loss: 0.0582 - accuracy: 0.9773 - val_loss: 0.0782 - val_accuracy: 0.9720

Training Accuracy: 0.98
In [21]:
# Accuracy-loss curves for training and validation data

acc = model_history_v1.history['accuracy']
val_acc = model_history_v1.history['val_accuracy']
loss = model_history_v1.history['loss']
val_loss = model_history_v1.history['val_loss']
epochs_range = range(1, len(model_history_v1.epoch) + 1)

plt.figure(figsize=(15,5))

plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Train Set',  color='royalblue')
plt.plot(epochs_range, val_acc, label='Val Set', color='firebrick')
plt.legend(loc="best")
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.title('Model Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, acc, label='Train Set',  color='royalblue')
plt.plot(epochs_range, val_acc, label='Val Set', color='firebrick')
plt.legend(loc="best")
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Model Loss')

plt.tight_layout()
plt.show()
No description has been provided for this image
In [22]:
# Save the model

model.save("model/MobileNetV2_with_Adam_Optimizer.keras")

Model Evaluation¶

In [23]:
# Make predictions on test data

predictions = model.predict(test_generator)
predicted_labels = np.round(predictions).flatten()
print(predicted_labels)

# Get the true labels and class names from test data
true_labels = test_generator.classes
class_names = test_generator.class_indices.keys()
157/157 [==============================] - 74s 468ms/step
[0. 1. 0. ... 0. 1. 0.]
In [24]:
# Accuracy Score

accuracy = accuracy_score(true_labels, predicted_labels)
print("\nAccuracy Score:", np.round(accuracy, 2))
Accuracy Score: 0.98
In [25]:
# Classification Report

print("\nClassification Report:\n")
print(classification_report(true_labels, predicted_labels, target_names=class_names, digits = 4))
Classification Report:

              precision    recall  f1-score   support

         cat     0.9906    0.9654    0.9778      2515
         dog     0.9659    0.9907    0.9781      2485

    accuracy                         0.9780      5000
   macro avg     0.9782    0.9781    0.9780      5000
weighted avg     0.9783    0.9780    0.9780      5000

In [26]:
# Define the confusion matrix

def plot_confusion_matrix(cm, target_names, title='Confusion Matrix', cmap=None, normalize=True):

    accuracy = np.trace(cm) / float(np.sum(cm))
    misclass = 1 - accuracy

    if cmap is None:
        cmap = plt.get_cmap('Blues')

    plt.figure(figsize=(8, 6))
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()

    if target_names is not None:
        tick_marks = np.arange(len(target_names))
        plt.xticks(tick_marks, target_names, rotation=45)
        plt.yticks(tick_marks, target_names)

    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    thresh = cm.max() / 1.5 if normalize else cm.max() / 2
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        if normalize:
            plt.text(j, i, "{:0.4f}".format(cm[i, j]),
                     horizontalalignment="center",
                     color="white" if cm[i, j] > thresh else "black")
        else:
            plt.text(j, i, "{:,}".format(cm[i, j]),
                     horizontalalignment="center",
                     color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label\naccuracy={:0.4f}; misclass={:0.4f}'.format(accuracy, misclass))
    plt.show()
In [27]:
# Confusion Matrix

confusion_mtx = confusion_matrix(true_labels, predicted_labels)

# Plot confusion matrix
plot_confusion_matrix(confusion_mtx, target_names=class_names, normalize=False)
No description has been provided for this image

Version 2: RMSProp Optimizer with Learning Rate Decay¶

In [28]:
# Define hyperparameters

input_shape = (img_height, img_width, 3)
learning_rate = 0.001
loss = 'binary_crossentropy'
metrics=['accuracy']
epochs = 30
In [29]:
# Construct the model

model = Sequential([base_model, Flatten(), Dense(256, activation='relu'), Dense(1, activation='sigmoid')])
In [30]:
# learning Rate Decay

# Define learning rate decay scheduler
def lr_scheduler(epoch, lr):
    return float(lr * tf.math.exp(-0.1))
In [31]:
# Compile the model

optimizer = RMSprop(learning_rate=learning_rate)
model.compile(optimizer=optimizer, loss=loss, metrics=metrics)

# Print model summary
model.summary()
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 mobilenetv2_1.00_224 (Funct  (None, 7, 7, 1280)       2257984   
 ional)                                                          
                                                                 
 flatten_1 (Flatten)         (None, 62720)             0         
                                                                 
 dense_2 (Dense)             (None, 256)               16056576  
                                                                 
 dense_3 (Dense)             (None, 1)                 257       
                                                                 
=================================================================
Total params: 18,314,817
Trainable params: 16,056,833
Non-trainable params: 2,257,984
_________________________________________________________________
In [32]:
# Define learning rate decay callback

lr_decay = LearningRateScheduler(lr_scheduler)
In [33]:
# Train the model

model_history_v2 = model.fit(train_generator, epochs=epochs, validation_data=validation_generator, batch_size=batch_size, callbacks=[lr_decay], verbose=1)

# Print the training accuracy
training_accuracy = model_history_v2.history['accuracy'][-1]
print("\nTraining Accuracy:", round(training_accuracy, 2))
Epoch 1/30
563/563 [==============================] - 441s 777ms/step - loss: 0.7283 - accuracy: 0.9488 - val_loss: 0.1663 - val_accuracy: 0.9665 - lr: 9.0484e-04
Epoch 2/30
563/563 [==============================] - 439s 780ms/step - loss: 0.1885 - accuracy: 0.9645 - val_loss: 0.1610 - val_accuracy: 0.9680 - lr: 8.1873e-04
Epoch 3/30
563/563 [==============================] - 435s 772ms/step - loss: 0.1536 - accuracy: 0.9667 - val_loss: 0.1307 - val_accuracy: 0.9700 - lr: 7.4082e-04
Epoch 4/30
563/563 [==============================] - 434s 771ms/step - loss: 0.1343 - accuracy: 0.9705 - val_loss: 0.2689 - val_accuracy: 0.9555 - lr: 6.7032e-04
Epoch 5/30
563/563 [==============================] - 435s 772ms/step - loss: 0.1188 - accuracy: 0.9727 - val_loss: 0.1305 - val_accuracy: 0.9745 - lr: 6.0653e-04
Epoch 6/30
563/563 [==============================] - 436s 774ms/step - loss: 0.1212 - accuracy: 0.9729 - val_loss: 0.1283 - val_accuracy: 0.9730 - lr: 5.4881e-04
Epoch 7/30
563/563 [==============================] - 435s 773ms/step - loss: 0.1043 - accuracy: 0.9738 - val_loss: 0.2234 - val_accuracy: 0.9560 - lr: 4.9659e-04
Epoch 8/30
563/563 [==============================] - 432s 768ms/step - loss: 0.1063 - accuracy: 0.9768 - val_loss: 0.1588 - val_accuracy: 0.9665 - lr: 4.4933e-04
Epoch 9/30
563/563 [==============================] - 436s 774ms/step - loss: 0.0893 - accuracy: 0.9789 - val_loss: 0.1212 - val_accuracy: 0.9760 - lr: 4.0657e-04
Epoch 10/30
563/563 [==============================] - 437s 776ms/step - loss: 0.0916 - accuracy: 0.9782 - val_loss: 0.1233 - val_accuracy: 0.9715 - lr: 3.6788e-04
Epoch 11/30
563/563 [==============================] - 438s 778ms/step - loss: 0.0822 - accuracy: 0.9797 - val_loss: 0.1205 - val_accuracy: 0.9730 - lr: 3.3287e-04
Epoch 12/30
563/563 [==============================] - 435s 772ms/step - loss: 0.0783 - accuracy: 0.9800 - val_loss: 0.1086 - val_accuracy: 0.9770 - lr: 3.0119e-04
Epoch 13/30
563/563 [==============================] - 436s 775ms/step - loss: 0.0744 - accuracy: 0.9826 - val_loss: 0.1309 - val_accuracy: 0.9720 - lr: 2.7253e-04
Epoch 14/30
563/563 [==============================] - 419s 744ms/step - loss: 0.0738 - accuracy: 0.9817 - val_loss: 0.1042 - val_accuracy: 0.9765 - lr: 2.4660e-04
Epoch 15/30
563/563 [==============================] - 402s 714ms/step - loss: 0.0629 - accuracy: 0.9836 - val_loss: 0.1177 - val_accuracy: 0.9730 - lr: 2.2313e-04
Epoch 16/30
563/563 [==============================] - 403s 715ms/step - loss: 0.0637 - accuracy: 0.9839 - val_loss: 0.1099 - val_accuracy: 0.9765 - lr: 2.0190e-04
Epoch 17/30
563/563 [==============================] - 408s 725ms/step - loss: 0.0593 - accuracy: 0.9842 - val_loss: 0.1720 - val_accuracy: 0.9690 - lr: 1.8268e-04
Epoch 18/30
563/563 [==============================] - 409s 726ms/step - loss: 0.0695 - accuracy: 0.9839 - val_loss: 0.1169 - val_accuracy: 0.9760 - lr: 1.6530e-04
Epoch 19/30
563/563 [==============================] - 412s 731ms/step - loss: 0.0594 - accuracy: 0.9852 - val_loss: 0.1589 - val_accuracy: 0.9735 - lr: 1.4957e-04
Epoch 20/30
563/563 [==============================] - 411s 730ms/step - loss: 0.0597 - accuracy: 0.9858 - val_loss: 0.0960 - val_accuracy: 0.9725 - lr: 1.3534e-04
Epoch 21/30
563/563 [==============================] - 410s 728ms/step - loss: 0.0515 - accuracy: 0.9865 - val_loss: 0.1173 - val_accuracy: 0.9750 - lr: 1.2246e-04
Epoch 22/30
563/563 [==============================] - 413s 733ms/step - loss: 0.0608 - accuracy: 0.9856 - val_loss: 0.0789 - val_accuracy: 0.9820 - lr: 1.1080e-04
Epoch 23/30
563/563 [==============================] - 412s 731ms/step - loss: 0.0500 - accuracy: 0.9879 - val_loss: 0.1144 - val_accuracy: 0.9750 - lr: 1.0026e-04
Epoch 24/30
563/563 [==============================] - 411s 729ms/step - loss: 0.0542 - accuracy: 0.9867 - val_loss: 0.1085 - val_accuracy: 0.9745 - lr: 9.0718e-05
Epoch 25/30
563/563 [==============================] - 414s 736ms/step - loss: 0.0459 - accuracy: 0.9892 - val_loss: 0.1168 - val_accuracy: 0.9755 - lr: 8.2085e-05
Epoch 26/30
563/563 [==============================] - 413s 734ms/step - loss: 0.0474 - accuracy: 0.9872 - val_loss: 0.1007 - val_accuracy: 0.9785 - lr: 7.4274e-05
Epoch 27/30
563/563 [==============================] - 412s 732ms/step - loss: 0.0444 - accuracy: 0.9886 - val_loss: 0.1337 - val_accuracy: 0.9735 - lr: 6.7206e-05
Epoch 28/30
563/563 [==============================] - 420s 745ms/step - loss: 0.0433 - accuracy: 0.9892 - val_loss: 0.0947 - val_accuracy: 0.9775 - lr: 6.0810e-05
Epoch 29/30
563/563 [==============================] - 423s 750ms/step - loss: 0.0354 - accuracy: 0.9899 - val_loss: 0.1155 - val_accuracy: 0.9800 - lr: 5.5023e-05
Epoch 30/30
563/563 [==============================] - 412s 731ms/step - loss: 0.0480 - accuracy: 0.9881 - val_loss: 0.1162 - val_accuracy: 0.9770 - lr: 4.9787e-05

Training Accuracy: 0.99
In [34]:
# Accuracy-loss curves for training and validation data

acc = model_history_v2.history['accuracy']
val_acc = model_history_v2.history['val_accuracy']
loss = model_history_v2.history['loss']
val_loss = model_history_v2.history['val_loss']
epochs_range = range(1, len(model_history_v2.epoch) + 1)

plt.figure(figsize=(15,5))

plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Train Set',  color='royalblue')
plt.plot(epochs_range, val_acc, label='Val Set', color='firebrick')
plt.legend(loc="best")
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.title('Model Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, acc, label='Train Set',  color='royalblue')
plt.plot(epochs_range, val_acc, label='Val Set', color='firebrick')
plt.legend(loc="best")
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Model Loss')

plt.tight_layout()
plt.show()
No description has been provided for this image
In [35]:
# Save the model

model.save("model/MobileNetV2_with_RMSProp_Optimizer.keras")

Model Evaluation¶

In [36]:
# Make predictions on test data

predictions = model.predict(test_generator)
predicted_labels = np.round(predictions).flatten()
print(predicted_labels)

# Get the true labels and class names from test data
true_labels = test_generator.classes
class_names = test_generator.class_indices.keys()
157/157 [==============================] - 68s 425ms/step
[0. 1. 0. ... 0. 1. 0.]
In [37]:
# Accuracy Score

accuracy = accuracy_score(true_labels, predicted_labels)
print("\nAccuracy Score:", np.round(accuracy, 2))
Accuracy Score: 0.98
In [38]:
# Classification Report

print("\nClassification Report:\n")
print(classification_report(true_labels, predicted_labels, target_names=class_names, digits = 4))
Classification Report:

              precision    recall  f1-score   support

         cat     0.9825    0.9821    0.9823      2515
         dog     0.9819    0.9823    0.9821      2485

    accuracy                         0.9822      5000
   macro avg     0.9822    0.9822    0.9822      5000
weighted avg     0.9822    0.9822    0.9822      5000

In [39]:
# Confusion Matrix

confusion_mtx = confusion_matrix(true_labels, predicted_labels)

# Plot confusion matrix
plot_confusion_matrix(confusion_mtx, target_names=class_names, normalize=False)
No description has been provided for this image

Version 3: SGD Optimizer with Momentum and Learning Rate Decay¶

In [40]:
# Define hyperparameters

input_shape = (img_height, img_width, 3)
learning_rate = 0.001
loss = 'binary_crossentropy'
metrics=['accuracy']
epochs = 30
In [41]:
# Construct the model

model = Sequential([base_model, Flatten(), Dense(256, activation='relu'), Dense(1, activation='sigmoid')])
In [42]:
# Compile the model

optimizer = SGD(learning_rate=learning_rate, momentum=0.9)
model.compile(optimizer=optimizer, loss=loss, metrics=metrics)

# Print model summary
model.summary()
Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 mobilenetv2_1.00_224 (Funct  (None, 7, 7, 1280)       2257984   
 ional)                                                          
                                                                 
 flatten_2 (Flatten)         (None, 62720)             0         
                                                                 
 dense_4 (Dense)             (None, 256)               16056576  
                                                                 
 dense_5 (Dense)             (None, 1)                 257       
                                                                 
=================================================================
Total params: 18,314,817
Trainable params: 16,056,833
Non-trainable params: 2,257,984
_________________________________________________________________
In [43]:
# Define learning rate decay callback

lr_decay = LearningRateScheduler(lr_scheduler)
In [44]:
# Train the model

model_history_v3 = model.fit(train_generator, epochs=epochs, validation_data=validation_generator, batch_size=batch_size, callbacks=[lr_decay], verbose=1)

# Print the training accuracy
training_accuracy = model_history_v3.history['accuracy'][-1]
print("\nTraining Accuracy:", round(training_accuracy, 2))
Epoch 1/30
563/563 [==============================] - 394s 693ms/step - loss: 0.0991 - accuracy: 0.9618 - val_loss: 0.0793 - val_accuracy: 0.9675 - lr: 9.0484e-04
Epoch 2/30
563/563 [==============================] - 392s 697ms/step - loss: 0.0697 - accuracy: 0.9721 - val_loss: 0.0654 - val_accuracy: 0.9720 - lr: 8.1873e-04
Epoch 3/30
563/563 [==============================] - 372s 661ms/step - loss: 0.0593 - accuracy: 0.9759 - val_loss: 0.0676 - val_accuracy: 0.9740 - lr: 7.4082e-04
Epoch 4/30
563/563 [==============================] - 369s 656ms/step - loss: 0.0550 - accuracy: 0.9786 - val_loss: 0.0624 - val_accuracy: 0.9755 - lr: 6.7032e-04
Epoch 5/30
563/563 [==============================] - 370s 658ms/step - loss: 0.0508 - accuracy: 0.9805 - val_loss: 0.0692 - val_accuracy: 0.9740 - lr: 6.0653e-04
Epoch 6/30
563/563 [==============================] - 387s 687ms/step - loss: 0.0510 - accuracy: 0.9806 - val_loss: 0.0638 - val_accuracy: 0.9735 - lr: 5.4881e-04
Epoch 7/30
563/563 [==============================] - 396s 703ms/step - loss: 0.0485 - accuracy: 0.9809 - val_loss: 0.0613 - val_accuracy: 0.9750 - lr: 4.9659e-04
Epoch 8/30
563/563 [==============================] - 396s 703ms/step - loss: 0.0473 - accuracy: 0.9823 - val_loss: 0.0627 - val_accuracy: 0.9760 - lr: 4.4933e-04
Epoch 9/30
563/563 [==============================] - 395s 701ms/step - loss: 0.0429 - accuracy: 0.9833 - val_loss: 0.0516 - val_accuracy: 0.9790 - lr: 4.0657e-04
Epoch 10/30
563/563 [==============================] - 401s 713ms/step - loss: 0.0429 - accuracy: 0.9839 - val_loss: 0.0619 - val_accuracy: 0.9750 - lr: 3.6788e-04
Epoch 11/30
563/563 [==============================] - 416s 738ms/step - loss: 0.0383 - accuracy: 0.9848 - val_loss: 0.0595 - val_accuracy: 0.9750 - lr: 3.3287e-04
Epoch 12/30
563/563 [==============================] - 384s 682ms/step - loss: 0.0366 - accuracy: 0.9859 - val_loss: 0.0658 - val_accuracy: 0.9735 - lr: 3.0119e-04
Epoch 13/30
563/563 [==============================] - 381s 677ms/step - loss: 0.0377 - accuracy: 0.9854 - val_loss: 0.0499 - val_accuracy: 0.9795 - lr: 2.7253e-04
Epoch 14/30
563/563 [==============================] - 381s 677ms/step - loss: 0.0374 - accuracy: 0.9866 - val_loss: 0.0582 - val_accuracy: 0.9750 - lr: 2.4660e-04
Epoch 15/30
563/563 [==============================] - 381s 676ms/step - loss: 0.0355 - accuracy: 0.9866 - val_loss: 0.0543 - val_accuracy: 0.9760 - lr: 2.2313e-04
Epoch 16/30
563/563 [==============================] - 383s 680ms/step - loss: 0.0341 - accuracy: 0.9876 - val_loss: 0.0621 - val_accuracy: 0.9770 - lr: 2.0190e-04
Epoch 17/30
563/563 [==============================] - 381s 675ms/step - loss: 0.0348 - accuracy: 0.9869 - val_loss: 0.0540 - val_accuracy: 0.9775 - lr: 1.8268e-04
Epoch 18/30
563/563 [==============================] - 381s 677ms/step - loss: 0.0339 - accuracy: 0.9865 - val_loss: 0.0615 - val_accuracy: 0.9730 - lr: 1.6530e-04
Epoch 19/30
563/563 [==============================] - 383s 679ms/step - loss: 0.0328 - accuracy: 0.9878 - val_loss: 0.0489 - val_accuracy: 0.9810 - lr: 1.4957e-04
Epoch 20/30
563/563 [==============================] - 382s 679ms/step - loss: 0.0317 - accuracy: 0.9875 - val_loss: 0.0530 - val_accuracy: 0.9780 - lr: 1.3534e-04
Epoch 21/30
563/563 [==============================] - 382s 678ms/step - loss: 0.0309 - accuracy: 0.9882 - val_loss: 0.0551 - val_accuracy: 0.9795 - lr: 1.2246e-04
Epoch 22/30
563/563 [==============================] - 381s 676ms/step - loss: 0.0332 - accuracy: 0.9879 - val_loss: 0.0585 - val_accuracy: 0.9785 - lr: 1.1080e-04
Epoch 23/30
563/563 [==============================] - 382s 678ms/step - loss: 0.0293 - accuracy: 0.9888 - val_loss: 0.0551 - val_accuracy: 0.9785 - lr: 1.0026e-04
Epoch 24/30
563/563 [==============================] - 382s 678ms/step - loss: 0.0312 - accuracy: 0.9881 - val_loss: 0.0563 - val_accuracy: 0.9785 - lr: 9.0718e-05
Epoch 25/30
563/563 [==============================] - 382s 678ms/step - loss: 0.0304 - accuracy: 0.9884 - val_loss: 0.0670 - val_accuracy: 0.9735 - lr: 8.2085e-05
Epoch 26/30
563/563 [==============================] - 382s 679ms/step - loss: 0.0293 - accuracy: 0.9888 - val_loss: 0.0548 - val_accuracy: 0.9780 - lr: 7.4274e-05
Epoch 27/30
563/563 [==============================] - 381s 677ms/step - loss: 0.0301 - accuracy: 0.9878 - val_loss: 0.0618 - val_accuracy: 0.9765 - lr: 6.7206e-05
Epoch 28/30
563/563 [==============================] - 382s 678ms/step - loss: 0.0298 - accuracy: 0.9887 - val_loss: 0.0513 - val_accuracy: 0.9790 - lr: 6.0810e-05
Epoch 29/30
563/563 [==============================] - 381s 677ms/step - loss: 0.0275 - accuracy: 0.9893 - val_loss: 0.0555 - val_accuracy: 0.9770 - lr: 5.5023e-05
Epoch 30/30
563/563 [==============================] - 382s 678ms/step - loss: 0.0293 - accuracy: 0.9887 - val_loss: 0.0685 - val_accuracy: 0.9775 - lr: 4.9787e-05

Training Accuracy: 0.99
In [45]:
# Accuracy-loss curves for training and validation data

acc = model_history_v3.history['accuracy']
val_acc = model_history_v3.history['val_accuracy']
loss = model_history_v3.history['loss']
val_loss = model_history_v3.history['val_loss']
epochs_range = range(1, len(model_history_v3.epoch) + 1)

plt.figure(figsize=(15,5))

plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Train Set',  color='royalblue')
plt.plot(epochs_range, val_acc, label='Val Set', color='firebrick')
plt.legend(loc="best")
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.title('Model Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, acc, label='Train Set',  color='royalblue')
plt.plot(epochs_range, val_acc, label='Val Set', color='firebrick')
plt.legend(loc="best")
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Model Loss')

plt.tight_layout()
plt.show()
No description has been provided for this image
In [46]:
# Save the model

model.save("model/MobileNetV2-V3_with_SGD_Optimizer.keras")

Model Evaluation¶

In [47]:
# Make predictions on test data

predictions = model.predict(test_generator)
predicted_labels = np.round(predictions).flatten()
print(predicted_labels)

# Get the true labels and class names from test data
true_labels = test_generator.classes
class_names = test_generator.class_indices.keys()
157/157 [==============================] - 74s 462ms/step
[0. 1. 0. ... 0. 1. 0.]
In [48]:
# Accuracy Score

accuracy = accuracy_score(true_labels, predicted_labels)
print("\nAccuracy Score:", np.round(accuracy, 2))
Accuracy Score: 0.98
In [49]:
# Classification Report

print("\nClassification Report:\n")
print(classification_report(true_labels, predicted_labels, target_names=class_names, digits = 4))
Classification Report:

              precision    recall  f1-score   support

         cat     0.9896    0.9797    0.9846      2515
         dog     0.9797    0.9895    0.9846      2485

    accuracy                         0.9846      5000
   macro avg     0.9846    0.9846    0.9846      5000
weighted avg     0.9846    0.9846    0.9846      5000

In [50]:
# Confusion Matrix

confusion_mtx = confusion_matrix(true_labels, predicted_labels)

# Plot confusion matrix
plot_confusion_matrix(confusion_mtx, target_names=class_names, normalize=False)
No description has been provided for this image

Application Phase¶

In [51]:
# Load the best model

loaded_model = load_model("model/MobileNetV2_with_Adam_Optimizer.keras")
In [52]:
# Run the model on unseen data from user

def predict_and_display_images(model, test_data_dir):
    test_files = os.listdir(test_data_dir)[:12]

    # Prepare subplots
    fig, axes = plt.subplots(3, 4, figsize=(15, 12))
    axes = axes.ravel()

    for i, filename in enumerate(test_files):
        # Load and preprocess image
        img_path = os.path.join(test_data_dir, filename)
        img = image.load_img(img_path, target_size=(224, 224))
        img_array = image.img_to_array(img)
        img_array = np.expand_dims(img_array, axis=0)
        img_array /= 255.0

        # Make prediction
        prediction = model.predict(img_array, verbose=0)
        predicted_class = "dog" if prediction > 0.5 else "cat"

        # Display the image
        axes[i].imshow(img)
        axes[i].set_title(f"Predicted: {predicted_class}", color='red')
        axes[i].axis('off')
        
        axes[i].set_ylim(img.size[1] + 10, -5)
        
    plt.tight_layout()
    plt.show()
In [53]:
# Usage

predict_and_display_images(model, test_data_dir)
No description has been provided for this image